package com.uzhie.util;

import com.google.common.base.Strings;
import com.uzhie.exception.SessionException;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.WebSocketSession;

import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by TangFei on 2018/8/14.
 */
public class SessionManager<T> {

    private Logger logger = Logger.getLogger(getClass());
    private Timer timer = new Timer("platSessionManagerThread", true);
    @Autowired(required = false)
    private CacheManager<String, Session> cacheManager;
    private long overTime;
    private long checkTime;

    public void setOverTime(long overTime) {
        this.overTime = overTime;
    }

    public void setCheckTime(long checkTime) {
        this.checkTime = checkTime;
    }

    /**
     * 设置socket信息
     * @param key
     * @param session
     */
    public void setSocketSession(String key, Session<T> session) {
        cacheManager.put(CacheManager.DES.PLA_SESSION_CACHE, key, session);
    }

    /**
     * 当有新的用户新增时,
     *
     * @param obj
     */
    public void set(String key, T obj) {
        if (obj == null) throw new IllegalArgumentException(SessionException.REQUEST_CODE_ISNULL);
        Session<T> session = new Session<T>();
        session.setObj(obj);
        session.setUpdateTime(System.currentTimeMillis() / 1000);
        cacheManager.put(CacheManager.DES.PLA_SESSION_CACHE, key, session);
    }

    /**
     * 通过requestCode获取服务器缓存的session值
     *
     * @param key 用户requestCode ,默认userCode
     * @return 用户session 如果用户session不存在,返回null
     * @throws NoSuchFieldException 如果session属性不存在,则抛出异常
     */
    public Session<T> get(String key) throws NoSuchFieldException {
        Session session = cacheManager.get(CacheManager.DES.PLA_SESSION_CACHE, key, Session.class);
        if (session == null) {
            throw new NoSuchFieldException(SessionException.SESSION_NOT_EXIST);
        } else {
            return session;
        }
    }

    /**
     * 获取所有用户ID
     *
     * @return
     */
    public List<String> getAllUserID() {
        return cacheManager.getKeys(CacheManager.DES.PLA_SESSION_CACHE);
    }

    /**
     * 把用户sesion从容器中清理出去
     *
     * @param key 用户requestCode ,默认userCode
     */
    public void delete(String key) {
        if (Strings.isNullOrEmpty(key)) {
            throw new IllegalArgumentException(SessionException.REQUEST_CODE_ISNULL);
        } else {
            cacheManager.remove(CacheManager.DES.PLA_SESSION_CACHE, key);
        }
    }

    /**
     * 当用户发起请求后,更新用户的session超时时间
     *
     * @param key 用户requestCode ,默认userCode
     * @throws NoSuchFieldException 如果session属性不存在,则抛出异常
     */
    public void updateTime(String key) throws NoSuchFieldException {
        if (Strings.isNullOrEmpty(key)) {
            throw new IllegalArgumentException(SessionException.REQUEST_CODE_ISNULL);
        } else {
            Session session = cacheManager.get(CacheManager.DES.PLA_SESSION_CACHE, key, Session.class);
            if (null == session) {
                throw new NoSuchFieldException(SessionException.SESSION_NOT_EXIST);
            } else {
                session.setUpdateTime(System.currentTimeMillis());
            }
        }
    }

    /**
     * session 超时计时器
     */
    public void scheduler() {
        logger.info(SessionException.SESSIONMANAGER_START_TIME);
        timer.schedule(new MyTimerTask(), checkTime, checkTime);
    }

    public class Session<T> {
        T obj;
        long updateTime;
        Map<String, WebSocketSession> socketSessionMap;

        public T getObj() {
            return obj;
        }

        public void setObj(T obj) {
            this.obj = obj;
        }

        public long getUpdateTime() {
            return updateTime;
        }

        public void setUpdateTime(long updateTime) {
            this.updateTime = updateTime;
        }

        public Map<String, WebSocketSession> getSocketSessionMap() {
            return socketSessionMap;
        }

        public void setSocketSessionMap(Map<String, WebSocketSession> socketSessionMap) {
            this.socketSessionMap = socketSessionMap;
        }
    }

    /**
     * 任务类,用来清理已经超时的session数据
     */
    private class MyTimerTask extends TimerTask {
        @Override
        public void run() {
            logger.info(SessionException.SESSION_START_CLEAR);

//            Set<String> keySet = cacheManager.getKeySet(CacheManager.DES.PLA_SESSION_CACHE);
//            for (String key : keySet) {
//                if (isOverTime(cacheManager.get(CacheManager.DES.PLA_SESSION_CACHE, key, Session.class))) {
//                    cacheManager.remove(CacheManager.DES.PLA_SESSION_CACHE, key);
//                    logger.info(SessionException.SESSION_CLEAR + ": code = " + key);
//                }
//            }
            logger.info(SessionException.SESSION_CLEAR_OVER);
            System.gc();
        }
    }

    /**
     * 判断session是否超时
     *
     * @return true 超时, false 不超时
     */
    public boolean isOverTime(Session session) {
        if (System.currentTimeMillis() / 1000 - session.getUpdateTime() / 1000 > overTime)
            return true;
        return false;
    }

}
